package com.gj.xxl.job.admin.core.thread;

import com.gj.xxl.job.admin.core.entity.JobInfo;
import com.gj.xxl.job.admin.core.trigger.GjJobTrigger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class JobTriggerHelper {

    private static Logger logger = LoggerFactory.getLogger(JobTriggerHelper.class);

    private static JobTriggerHelper instance = new JobTriggerHelper();

    public static JobTriggerHelper getInstance() {
        return instance;
    }

    //触发任务的线程池
    //假设线程池有 100 个线程，但是有 10 个定时任务的执行耗时比较长，那么 10 个线程不就被占据了吗，其他定时任务就拿不到这 10 个线程了
    //而且我们知道定时任务不是只执行一次的，假如说这 10 个定时任务的执行频率比较高，那么线程池的线程不就被消耗完了吗？
    //那么整个线程池不久废了吗，其他的定时任务都不无法被触发了
    //怎么解决呢？
    //既然耗时短的任务会被耗时长的任务给拖累，那么就使用两个线程池分别处理慢的任务和快的任务
    //快慢线程池
    private ThreadPoolExecutor slowTriggerJobThreadPool;
    private ThreadPoolExecutor fastTriggerJobThreadPool;
    private AtomicInteger slowIndex = new AtomicInteger(0);
    private AtomicInteger fastIndex = new AtomicInteger(0);

    public void start() {

        slowTriggerJobThreadPool = new ThreadPoolExecutor(
                10,
                100,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(100),
                r -> {
                    Thread thread = new Thread(r);
                    thread.setName("SlowTriggerJobThread" + slowIndex.incrementAndGet());
                    return thread;
                },
                (r, executor) -> {
                    throw new RuntimeException("slowTriggerJobThreadPool 触发拒绝策略");
                }
        );
        fastTriggerJobThreadPool = new ThreadPoolExecutor(
                10,
                100,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(100),
                r -> {
                    Thread thread = new Thread(r);
                    thread.setName("FastTriggerJobThread" + fastIndex.incrementAndGet());
                    return thread;
                },
                (r, executor) -> {
                    throw new RuntimeException("fastTriggerJobThreadPool 触发拒绝策略");
                }
        );


    }

    private Set<Integer> sloJobSet = new HashSet<>();

    public void trigger(JobInfo jobInfo) {
        //如何判断任务到底是给慢线程池执行还是给快线程池执行呢
        //根据任务的耗时呗

        long start = System.currentTimeMillis();

        if (sloJobSet.contains(jobInfo.getId())) {
            slowTriggerJobThreadPool.execute(() -> {
                logger.info("任务 job Id = " + jobInfo.getId() + " 被线程:" + Thread.currentThread().getName() + " 触发了");
                GjJobTrigger.getInstance().trigger(jobInfo);
            });
        } else {
            fastTriggerJobThreadPool.execute(() -> {
                logger.info("任务 job Id = " + jobInfo.getId() + " 被线程:" + Thread.currentThread().getName() + " 触发了");
                GjJobTrigger.getInstance().trigger(jobInfo);
                try {
                    logger.info("模拟网络卡顿 1 s");
                    Thread.sleep(1000);
                    long cost = System.currentTimeMillis() - start;
                    if (cost > 500) {
                        sloJobSet.add(jobInfo.getId());
                    }
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            });
        }
    }

    public void destroy() {
        slowTriggerJobThreadPool.shutdown();
        fastTriggerJobThreadPool.shutdown();
    }
}
